home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-09-24 | 4.7 KB | 184 lines | [TEXT/MPS ] |
- (* Weight-balanced binary trees.
- These are binary trees such that one child of a node has at most N times
- as many elements as the other child. We take N=3. *)
-
- #open "int";;
- #open "eq";;
- #open "exc";;
-
- (* Compute the size (number of nodes and leaves) of a tree. *)
-
- let size = function
- Empty -> 1
- | Node(_, _, _, s) -> s;;
-
- (* Creates a new node with left son l, value x and right son r.
- l and r must be balanced and size l / size r must be between 1/N and N.
- Inline expansion of size for better speed. *)
-
- let new l x r =
- let sl = match l with Empty -> 0 | Node(_,_,_,s) -> s in
- let sr = match r with Empty -> 0 | Node(_,_,_,s) -> s in
- Node(l, x, r, sl + sr + 1);;
-
- (* Same as new, but performs rebalancing if necessary.
- Assumes l and r balanced, and size l / size r "reasonable"
- (between 1/N^2 and N^2 ???).
- Inline expansion of new for better speed in the most frequent case
- where no rebalancing is required. *)
-
- let bal l x r =
- let sl = match l with Empty -> 0 | Node(_,_,_,s) -> s in
- let sr = match r with Empty -> 0 | Node(_,_,_,s) -> s in
- if sl > 3 * sr then
- let (Node(ll, lv, lr, _)) = l in
- if size ll >= size lr then
- new ll lv (new lr x r)
- else
- let (Node(lrl, lrv, lrr, _)) = lr in
- new (new ll lv lrl) lrv (new lrr x r)
- else if sr > 3 * sl then
- let (Node(rl, rv, rr, _)) = r in
- if size rr >= size rl then
- new (new l x rl) rv rr
- else
- let (Node(rll, rlv, rlr, _)) = rl in
- new (new l x rll) rlv (new rlr rv rr)
- else
- Node(l, x, r, sl + sr + 1);;
-
- (* Same as bal, but rebalance regardless of the original ratio
- size l / size r *)
-
- let rec join l x r =
- let (Node(l', x', r', _) as t') = bal l x r in
- let sl = size l' and sr = size r' in
- if sl > 3 * sr or sr > 3 * sl then join l' x' r' else t'
- ;;
-
- (* Merge two trees l and r into one.
- All elements of l must precede the elements of r.
- Assumes size l / size r between 1/N and N. *)
-
- let rec merge = fun
- Empty t -> t
- | t Empty -> t
- | (Node(l1, v1, r1, h1)) (Node(l2, v2, r2, h2)) ->
- bal l1 v1 (bal (merge r1 l2) v2 r2)
- ;;
-
- (* Same as merge, but does not assume anything about l and r. *)
-
- let rec concat = fun
- Empty t -> t
- | t Empty -> t
- | (Node(l1, v1, r1, h1)) (Node(l2, v2, r2, h2)) ->
- join l1 v1 (join (concat r1 l2) v2 r2)
- ;;
-
- (* Insertion *)
-
- let add searchpred x t =
- let rec add = function
- Empty ->
- Node(Empty, x, Empty, 1)
- | Node(l, v, r, _) as t ->
- let c = searchpred v in
- if c == 0 then t else
- if c < 0 then bal (add l) v r else bal l v (add r)
- in add t
- ;;
-
- (* Membership *)
-
- let contains searchpred t =
- let rec contains = function
- Empty -> false
- | Node(l, v, r, _) ->
- let c = searchpred v in
- if c == 0 then true else
- if c < 0 then contains l else contains r
- in contains t
- ;;
-
- (* Search *)
-
- let find searchpred t =
- let rec find = function
- Empty ->
- raise Not_found
- | Node(l, v, r, _) ->
- let c = searchpred v in
- if c == 0 then v else
- if c < 0 then find l else find r
- in find t
- ;;
-
- (* Deletion *)
-
- let remove searchpred t =
- let rec remove = function
- Empty ->
- Empty
- | Node(l, v, r, _) ->
- let c = searchpred v in
- if c == 0 then merge l r else
- if c < 0 then bal (remove l) v r else bal l v (remove r)
- in remove t
- ;;
-
- (* Modification *)
-
- let modify searchpred modifier t =
- let rec modify = function
- Empty ->
- begin match modifier Nothing with
- Nothing -> Empty
- | Something v -> Node(Empty, v, Empty, 1)
- end
- | Node(l, v, r, s) ->
- let c = searchpred v in
- if c == 0 then
- begin match modifier(Something v) with
- Nothing -> merge l r
- | Something v' -> Node(l, v', r, s)
- end
- else if c < 0 then bal (modify l) v r else bal l v (modify r)
- in modify t
- ;;
-
- (* Splitting *)
-
- let split searchpred =
- let rec split = function
- Empty ->
- (Empty, Nothing, Empty)
- | Node(l, v, r, _) ->
- let c = searchpred v in
- if c == 0 then (l, Something v, r)
- else if c < 0 then
- let (ll, vl, rl) = split l in (ll, vl, join rl v r)
- else
- let (lr, vr, rr) = split r in (join l v lr, vr, rr)
- in split
- ;;
-
- (* Comparison (by lexicographic ordering of the fringes of the two trees). *)
-
- let compare cmp s1 s2 =
- let rec compare_aux = fun
- [] [] -> 0
- | [] _ -> -1
- | _ [] -> 1
- | (Empty::t1) (Empty::t2) ->
- compare_aux t1 t2
- | (Node(Empty, v1, r1, _) :: t1) (Node(Empty, v2, r2, _) :: t2) ->
- let c = cmp v1 v2 in
- if c != 0 then c else compare_aux (r1::t1) (r2::t2)
- | (Node(l1, v1, r1, _) :: t1) t2 ->
- compare_aux (l1 :: Node(Empty, v1, r1, 0) :: t1) t2
- | t1 (Node(l2, v2, r2, _) :: t2) ->
- compare_aux t1 (l2 :: Node(Empty, v2, r2, 0) :: t2)
- in
- compare_aux [s1] [s2];;
-